
<template>
  <div class="onekit-map"
       :class="onekitClass"
       :style="onekitStyle"
       :id="onekitId"
       :data-mapId="mapId">
    <div :id="mapId"
         style="height:100%;width:100%;">
    </div>
    <div v-if="controls && controls.length > 0"
         style="background:#f008;position:absolute;left:0;top:0;width:100%;height:100%;pointer-events: none;">
      <img v-for="(item,index) in controls"
           :key="index"
           :id="item.id || new Date().getTime()"
           :style="{left:item.position.left + 'px',
                    top:item.position.top + 'px',
                    width:item.position.width + 'px',
                    height:item.position.height + 'px'}"
           :src="item.iconPath"
           alt=""
           style="pointer-events:auto;position: absolute; z-index: 99;"
           @click="map_controltap(item.id,item.clickable)">
    </div>
  </div>
</template>

<script>
/* eslint-disable vue/require-prop-type-constructor */
import weixin_behavior from "../../behaviors/weixin_behavior"
import onekit_behavior from "../../behaviors/onekit_behavior"
import MapContext_behavior from "../../api/MapContext_behavior"

const _wx_labels = {};
const _wx_markers = {};
const _web_multiMarkers = [];
const _web_infoWindows = {};
export default {
  name: "onekit-map",
  mixins: [weixin_behavior, onekit_behavior, MapContext_behavior],
  data () {
    return {
      mapId: `id${new Date().getTime()}`,
      position: {
        longitude: this.longitude,
        latitude: this.latitude
      }
    }
  },
  props: {
    longitude: { type: [String, Number], required: true },
    latitude: { type: [String, Number], required: true },
    scale: { type: [String, Number], default: 16 },
    'min-scale': { type: [String, Number], default: 3 },
    'max-scale': { ype: [String, Number], default: 20 },
    markers: Array,
    polyline: Array,
    circles: Array,
    controls: Array,
    'include-points': Array,
    'show-location': { type: String | Boolean, default: false },
    polygons: Array,
    subkey: String,
    'layer-style': { type: [String, Number], default: 1 },
    rotate: { type: [String, Number], default: 0 },
    skew: { type: [String, Number], default: 0 },
    enable3D: { type: [Boolean, String], default: false },
    //
    showCompass: { type: [Boolean, String], default: false },
    showScale: { type: [Boolean, String], default: false },
    enableOverlooking: { type: [Boolean, String], default: false },
    enableZoom: { type: [Boolean, String], default: true },
    enableScroll: { type: [Boolean, String], default: true },
    //
    enableRotate: { type: [Boolean, String], default: false },
    enableSatellite: { type: [Boolean, String], default: false },
    enableTraffic: { type: [Boolean, String], default: false },
    enablePoi: { type: [Boolean, String], default: true },
    enableBuilding: { type: [Boolean, String], default: true },
    setting: Object
  },
  created () {
    if (!window.onekit_nodes) {
      window.onekit_nodes = {}
    }
    window.onekit_nodes[`_${this.onekitId}`] = this
  },
  mounted () {
    if (this.showLocation) {
      navigator.geolocation.getCurrentPosition((position) => {
        // return position
        this.map.on('click', () => {
          const data = {
            detail: {
              latitude: position.coords.longitude,
              longitude: position.coords.latitude,
            }
          }
          this.$emit('AnchorPointTap', data)
        })
      })
    }
    this.init_()
    //
    this.markers_(this.markers || [], true)
    this.polylines_(this.polyline || [])
    this.circles_(this.circles || [])
    //
    const padding = [{ top: 0, bottom: 0, left: 0, right: 0 }]
    this.includePoints_(this.includePoints || [], padding)
    //
    this.polygons_(this.polygons || [])
    this.showScale_(this.showScale)
    this.enableZoom_(this.enableZoom)
    this.enableScroll_(this.enableScroll)
    this.initEvents_()
    this.boundsChangedEvents_()
    this._trigger_poitap()
  },
  watch: {
    markers (markers) {
      this.markers_(markers, true);
    },
  },
  methods: {
    //
    init_ () {
      let rotate = this.rotate / 40 * 45
      let skew = this.skew
      let baseMap = {}
      let mode
      if (this.enableSatellite) {
        baseMap = {
          type: 'satellite'
        }
      }
      if (this.enableTraffic) {
        baseMap = {
          type: 'traffic'
        }
      }
      if (!this.enablePoi) {
        baseMap = {
          type: 'vector',
          features: ['base', 'building2d']
        }
      }
      if (this.enable3D) {
        mode = '3D'
      } else {
        mode = '2D'
      }
      mode = '3D'
      if (this.enableOverlooking) {
        skew = 40
      }

      //
      // let clusterIdList = []
      // let joinClusterList = []
      // let ariaLabelList = []
      //

      //init
      let myLatlng = new TMap.LatLng(this.position.latitude, this.position.longitude);
      let myOptions = {
        center: myLatlng,
        zoom: this.scale,
        minZoom: this.minScale,
        maxZoom: this.maxScale,
        pitch: skew,
        rotation: rotate,
        mapStyleId: 'style' + this.layerStyle,
        scrollable: this.enableZoom,
        doubleClickZoom: this.enableZoom,
        draggable: this.enableScroll,
        baseMap: baseMap,
        viewMode: mode,
        /* 
          setting = {
            showLocation: false,
            showScale: false,
            subKey: '',
            enableRotate: false,
            showCompass: false,
            enableOverlooking: false,
          }
        */
      }
      this.map = new TMap.Map(this.mapId, this.setting || myOptions);
    },
    marker_ (markerId) {
      for (const web_multiMarker of _web_multiMarkers) {
        const web_marker = web_multiMarker.getGeometries().find((web_marker) => {
          return web_marker.id = markerId
        })
        if (web_marker) {
          return web_multiMarker
        }
      }
    },
    markers_ (wx_markers, clear) {
      if (clear) {
        _web_multiMarkers.forEach((web_multiMarker) => {
          web_multiMarker.remove(web_multiMarker.getGeometries().map((web_marker) => web_marker.id))
        })
        _web_multiMarkers.length = 0
      }
      wx_markers.forEach(wx_marker => {
        const web_pointGeometrie = {
          id: wx_marker.id || new Date().getTime(),
          styleId: "myStyle",
          position: new TMap.LatLng(wx_marker.latitude, wx_marker.longitude),
        }
        if (wx_marker.zIndex) {
          web_pointGeometrie.rank = wx_marker.zIndex
        }
        if ((wx_marker.name || wx_marker.title) && wx_marker.callout && wx_marker.customCallout) {
          wx_marker.callout = wx_marker.name = wx_marker.title = {}
        }
        //
        wx_marker.width = wx_marker.width || 35
        wx_marker.height = wx_marker.height || 50
        wx_marker.anchor = wx_marker.anchor || { x: .5, y: 1 }
        /////////////////////////////////////////////////////////////
        const web_marker = new TMap.MultiMarker({
          map: this.map,
          styles: {
            "myStyle": new TMap.MarkerStyle({
              width: wx_marker.width,
              height: wx_marker.height,
              anchor: { x: wx_marker.anchor.x * wx_marker.width, y: wx_marker.anchor.y * wx_marker.height },
              src: wx_marker.iconPath,
              rotate: wx_marker.rotate,
              opacity: wx_marker.alpha
            })
          },
          geometries: [web_pointGeometrie]
        })
        _web_multiMarkers.push(web_marker)
        const web_markerId = web_marker.geometries[0].id
        _wx_markers[`marker_${web_markerId}`] = wx_marker
        //
        if (web_marker) {
          web_marker.on('click', (evt) => {
            const data = {
              detail: {
                markerId: evt.geometry.id
              }
            }
            this.$emit('Markertap', data)
          })
        }
        ///////////////////////////////////////////////////////////////////////////
        if (wx_marker.customCallout || wx_marker.callout) {
          wx_marker.callout = wx_marker.callout || {}
          wx_marker.callout = {
            content: wx_marker.callout.content || "",
            // color: wx_marker.callout.color || "",
            // fontSize: wx_marker.callout.fontSize || 0,
            // borderRadius: wx_marker.callout.borderRadius || 0,
            // borderWidth: wx_marker.callout.borderWidth || 0,
            // borderColor: wx_marker.callout.borderColor || "",
            // bgColor: wx_marker.callout.bgColor || "",
            // padding: wx_marker.callout.padding || 0,
            display: wx_marker.callout.display || "BYCLICK",
            // textAlign: wx_marker.callout.textAlign || "center",
            anchorX: wx_marker.callout.anchorX || 0,
            anchorY: wx_marker.callout.anchorY || -50
          }
          //
          wx_marker.customCallout = wx_marker.customCallout || {}
          wx_marker.customCallout = {
            display: wx_marker.customCallout.display || "BYCLICK",
            anchorX: wx_marker.customCallout.anchorX || 0,
            anchorY: wx_marker.customCallout.anchorY || -50
          }
          const web_infoWindow = new TMap.InfoWindow({
            map: this.map,
            position: new TMap.LatLng(wx_marker.latitude, wx_marker.longitude),
            content: wx_marker.customCallout.content || wx_marker.callout.content || wx_marker.name || wx_marker.title,
            offset: { x: wx_marker.customCallout.anchorX || wx_marker.callout.anchorX, y: wx_marker.customCallout.anchorY || wx_marker.callout.anchorY }
          })
          _web_infoWindows[web_markerId] = web_infoWindow
          console.log(_web_infoWindows)
          web_infoWindow.close();//初始关闭信息窗关闭
          switch (wx_marker.callout.display) {
            case 'BYCLICK':
              break;
            case 'ALWAYS':
              web_infoWindow.open()
              break;
            default:
              throw new Error();
          }
          web_marker.on("click", (evt) => {
            const web_markerId = evt.geometry.id
            //
            const web_infoWindow = _web_infoWindows[web_markerId]
            if (web_infoWindow) {
              web_infoWindow.open();
            }
            //
            if (web_infoWindow.content) {
              const data = {
                detail: {
                  markerId: evt.geometry.id
                }
              }
              this.$emit('Callout', data)
            }
          })
        }
        ////////////////////////////////////////////////////////////////////////////////
        if (wx_marker.label) {
          const web_labelGeometry = {
            id: wx_marker.id || new Date().getTime(),
            styleId: "label",
            position: new TMap.LatLng(wx_marker.latitude, wx_marker.longitude),
          }
          web_labelGeometry.content = wx_marker.label.content || ''
          if (wx_marker.zIndex) {
            web_pointGeometrie.rank = wx_marker.zIndex
          }
          wx_marker.label = wx_marker.label || {}
          web_marker.label = {
            color: wx_marker.label.color || "rgba(0,0,0,1)",
            fontSize: wx_marker.label.fontSize || 14,
            anchorX: wx_marker.label.anchorX || 0,
            anchorY: wx_marker.label.anchorY || -50,
            // borderWidth: wx_marker.label.borderWidth || 0,
            // borderColor: wx_marker.label.borderColor || "",
            // borderRadius: wx_marker.label.borderRadius || 0,
            // bgColor: wx_marker.label.bgColor || "",
            // padding: wx_marker.label.padding || 0,
            textAlign: wx_marker.label.textAlign || "center",
          }
          const web_label = new TMap.MultiLabel({
            map: this.map,
            styles: {
              'label': new TMap.LabelStyle({
                color: web_marker.label.color,
                size: web_marker.label.fontSize,
                offset: { x: web_marker.label.anchorX || 20, y: web_marker.label.anchorY || 30 },
                alignment: web_marker.label.textAlign,
              })
            },
            geometries: [web_labelGeometry]
          })
          _wx_labels[`labe_${web_label.geometries[0].id}`] = wx_marker.label
          //
          if (web_labelGeometry.content) {
            web_label.on('click', (evt) => {
              const data = {
                detail: {
                  markerId: evt.geometry.id
                }
              }
              this.$emit('Labeltap', data)
            })
          }
        }
      })
    },
    polylines_ (wx_polylines) {
      wx_polylines.forEach(wx_polyline => {
        const web_paths = wx_polyline.points.map(point => {
          return new TMap.LatLng(point.latitude, point.longitude)
        })
        if (wx_polyline.colorList.length && wx_polyline.color) {
          wx_polyline.color = wx_polyline.colorList[wx_polyline.colorList.length - 1]
        }
        let web_rainbowPath = web_paths.map((p, i) => {
          const web_color = wx_polyline.colorList ? wx_polyline.colorList[i < web_paths.length ? i : (web_paths.length - 1)] : wx_polyline.color
          return {
            path: [web_paths[i], web_paths[i + 1]],
            color: web_color
          }
        })
        web_rainbowPath.pop()
        const web_polylineGeometry = {
          id: wx_polyline.id || new Date().getTime(),
          styleId: "polyline",
          rainbowPaths: web_rainbowPath
        }
        let dashArray = []
        if (wx_polyline.dottedLine) {
          dashArray = [4, 4]
        } else {
          dashArray = [0, 0]
        }
        /*
          arrowIconPath //更换箭头图标
          level //压盖关系
        */
        ////////////////////////////////////////////////////////////////
        new TMap.MultiPolyline({
          map: this.map,
          styles: {
            'polyline': new TMap.PolylineStyle({
              color: wx_polyline.color || '#000000',
              width: wx_polyline.width || 3,
              borderWidth: wx_polyline.borderWidth || 1,
              borderColor: wx_polyline.borderColor || '#3777FF',
              lineCap: 'round',
              dashArray: dashArray,
              showArrow: wx_polyline.arrowLine
              // arrowOptions :{
              //   width:
              //   height:
              //   space:
              // }
            })
          },
          //折线数据定义
          geometries: [web_polylineGeometry]
        })
      })
    },
    circles_ (wx_circles) {
      wx_circles.forEach(wx_circle => {
        const web_circleGeometry = {
          id: wx_circle.id || new Date().getTime(),
          styleId: "circle",
          center: new TMap.LatLng(wx_circle.latitude, wx_circle.longitude),
          radius: wx_circle.radius
        }
        /*
          level //压盖关系
        */
        ///////////////////////////////////////////////////////////////
        new TMap.MultiCircle({
          map: this.map,
          styles: { // 设置圆形样式
            'circle': new TMap.CircleStyle({
              color: wx_circle.fillColor || 'rgba(255,255,255,0.2)',
              showBorder: true,
              borderColor: wx_circle.color || '#000000',
              borderWidth: wx_circle.strokeWidth || 1,
            })
          },
          geometries: [web_circleGeometry],
        })
      })
    },
    includePoints_ (wx_includePoints, padding) {
      if (!wx_includePoints || wx_includePoints.length <= 0) {
        return;
      }
      let web_latlngBounds = new TMap.LatLngBounds()
      wx_includePoints.forEach(wx_point => {
        const web_point = new TMap.LatLng(wx_point.latitude, wx_point.longitude)
        web_latlngBounds.extend(web_point)
      })
      let fitBoundsOptions = {}
      if (padding[0].top !== 0 && padding[0].bottom !== 0 && padding[0].left !== 0 && padding[0].right !== 0) {
        fitBoundsOptions.padding = padding[0]
      }
      this.map.fitBounds(web_latlngBounds, fitBoundsOptions)
    },
    polygons_ (wx_polygons) {
      wx_polygons.forEach(wx_polygon => {
        const web_paths = wx_polygon.points.map(point => {
          return new TMap.LatLng(point.latitude, point.longitude)
        })
        const web_polygonGeometry = {
          id: wx_polygon.id || new Date().getTime(),
          styleId: "polygon",
          paths: web_paths
        }
        if (wx_polygon.zIndex) {
          web_polygonGeometry.rank = wx_polygon.zIndex
        }
        /*
          level //压盖关系
        */
        //////////////////////////////////////////////////
        new TMap.MultiPolygon({
          map: this.map,
          styles: {
            'polygon': new TMap.PolygonStyle({
              color: wx_polygon.fillColor || '#000000',
              showBorder: true,
              borderColor: wx_polygon.strokeColor || '#3777FF',
              borderWidth: wx_polygon.strokeWidth || 1,
            })
          },
          geometries: [web_polygonGeometry]
        })
      })
    },
    showScale_ (wx_showsScale) {
      let control = this.map.getControl(TMap.constants.DEFAULT_CONTROL_ID.SCALE)
      // 移除缩放控件
      if (!this.map.getControl(TMap.constants.DEFAULT_CONTROL_ID.ZOOM) && !this.map.getControl(TMap.constants.DEFAULT_CONTROL_ID.SCALE)) {
        //差罗盘已向上报告
        return;
      }
      this.map.removeControl(TMap.constants.DEFAULT_CONTROL_ID.ZOOM);
      this.map.removeControl(TMap.constants.DEFAULT_CONTROL_ID.SCALE);

      //比例尺
      if (wx_showsScale) {
        if (!control || this.map.getControl(TMap.constants.DEFAULT_CONTROL_ID.SCALE)) {
          return;
        }
        this.map.addControl(control);
      }
      //缩放
      // if (!wx_enableZoom) {
      //   if (!control[1] || this.map.getControl(TMap.constants.DEFAULT_CONTROL_ID.ZOOM)) {
      //     return;
      //   }
      //   this.map.addControl(control[1]);
      // }
      //罗盘
      // if (wx_showCompass) {
      //   console.log(wx_showCompass)
      //   // if (!control || this.map.getControl(TMap.constants.DEFAULT_CONTROL_ID.ZOOM)) {
      //   //   return;
      //   // }
      //   // this.map.addControl(control);
      // }
    },
    enableZoom_ (wx_enableZoom) {
      if (!wx_enableZoom) {
        this.map.setScrollable(false)
        this.map.setDoubleClickZoom(false)
      }
    },
    enableScroll_ (wx_enableScroll) {
      if (!wx_enableScroll) {
        this.map.setDraggable(false)
      }
    },
    ////////////////////////////////////////////
    initEvents_ () {
      this.map.on('click', (e) => {
        const data = {
          detail: {
            longitude: e.latLng.getLat(),
            latitude: e.latLng.getLng()
          },
        }
        this.$emit('Tap', data)
      })
    },
    map_controltap (wx_controlId, wx_clickable) {
      if (wx_clickable) {
        const data = {
          detail: {
            controlId: wx_controlId
          }
        }
        this.$emit('Controltap', data)
      }
    },
    //
    _trigger_updated () {
      this.map.destroy()
      this.initEvents_()
      this.$emit('Updated')
    },
    boundsChangedEvents_ () {
      this.map.on('bounds_changed', (e) => {
        const data = {
          causedBy: 'update',
          detail: {
            centerLocation: { latitude: (e.bounds._ne.lat + e.bounds._sw.lat) / 2, longitude: (e.bounds._ne.lng + e.bounds._sw.lng) / 2 },
            gesture: undefined,
            region: {
              northeast: { latitude: e.bounds._ne.lat, longitude: e.bounds._ne.lng },
              southwest: { latitude: e.bounds._sw.lat, longitude: e.bounds._sw.lng }
            },
            rotate: 0,
            scale: 16,
            skew: 0,
            type: "end",
          },
          touches: []
        }
        this.$emit('RegionChange', data)
      })
    },
    _trigger_poitap () {
      let info = new TMap.InfoWindow({
        map: this.map,
        position: this.map.getCenter()
      }).close();
      this.map.on('click', (evt) => {
        if (evt.poi) {
          info.close()
          const data = {
            detail: {
              latitude: evt.poi.latLng.lat, longitude: evt.poi.latLng.lng,
              name: evt.poi.name
            }
          }
          this.$emit('Poitap', data)
        }
      })
    },
  },
}
</script>

<style>
</style>
